package com.example.block_chain.service.impl.blockChain;

import com.example.block_chain.service.blockChain.IpfsService;
import io.ipfs.api.IPFS;
import io.ipfs.api.NamedStreamable;
import io.ipfs.api.WriteFilesArgs;
import io.ipfs.multiaddr.MultiAddress;
import io.ipfs.multihash.Multihash;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

@Service
public class IpfsServiceImpl implements IpfsService {
    @Value("${ipfs.config.multi-addr}")
    private String multiAddr;
    private final IPFS ipfs;

    public IpfsServiceImpl() {
        this.ipfs = new IPFS(new MultiAddress("/ip4/127.0.0.1/tcp/5001"));
    }

    @Override
    public void createDirectory(String path) throws IOException {
        ipfs.files.mkdir(path, true);
    }

    @Override
    public Map<String, Object> getDirectoryStats(String path) throws IOException {
        return ipfs.files.stat(path);
    }

    @Override
    public void addFile(String directoryPath, String filename, byte[] content) throws IOException {
        NamedStreamable file = new NamedStreamable.ByteArrayWrapper(filename, content);
        ipfs.files.write(directoryPath, file, true, true);
    }

    @Override
    public void writeFileUsingBuilder(String directoryPath, String filename, byte[] content) throws IOException {
        NamedStreamable file = new NamedStreamable.ByteArrayWrapper(filename, content);
        WriteFilesArgs args = WriteFilesArgs.Builder.newInstance()
                .setCreate()
                .setParents()
                .build();
        ipfs.files.write(directoryPath + "/" + filename, file, args);
    }

    @Override
    public String readFile(String filePath) throws IOException {
        return new String(ipfs.files.read(filePath));
    }

    @Override
    public List<Map> listDirectory(String path) throws IOException {
        return ipfs.files.ls(path);
    }

    @Override
    public void copy(String source, String destination) throws IOException {
        ipfs.files.cp(source, destination, true);
    }

    @Override
    public void move(String source, String destination) throws IOException {
        ipfs.files.mv(source, destination);
    }

    @Override
    public void remove(String path, boolean recursive) throws IOException {
        ipfs.files.rm(path, recursive, true);
    }

    @Override
    public String uploadFileFromStream(String filePath, InputStream inputStream) throws IOException {
        NamedStreamable.InputStreamWrapper file = new NamedStreamable.InputStreamWrapper(inputStream);
        ipfs.files.write(filePath, file, true, true);
        return getFileHashByFilePath(filePath);
    }

    //根据文件路径+文件名获取文件hash
    @Override
    public String getFileHashByFilePath(String filePath) throws IOException {
        return (String) ipfs.files.stat(filePath).get("Hash");
    }

    //根据文件cid检查是否存在此文件
    @Override
    public boolean checkFileByFileCid(String fileCid) {
        try {
            Multihash decode = Multihash.decode(fileCid);
            ipfs.block.stat(decode);
            return true;
        } catch (IllegalStateException e) {
            return false;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
